/*
 *
 * Copyright (c) 2020 The Raptor Authors. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#ifndef RAPTOR_LITE_SRC_WINDOWS_TCP_CONNECTOR_H_
#define RAPTOR_LITE_SRC_WINDOWS_TCP_CONNECTOR_H_

#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <string>

#include "raptor-lite/utils/list_entry.h"
#include "raptor-lite/utils/thread.h"
#include "raptor-lite/utils/sync.h"
#include "raptor-lite/utils/mpscq.h"
#include "raptor-lite/impl/property.h"

#include "src/common/resolve_address.h"
#include "src/common/sockaddr.h"
#include "src/common/common.h"
#include "src/windows/iocp_thread.h"

namespace raptor {
class ConnectorHandler;
class PollingThread;

struct AsyncConnectObject;

class TcpConnector final : public internal::EventReceivingService {
public:
    explicit TcpConnector(ConnectorHandler *handler);
    ~TcpConnector();

    raptor_error Init(PollingThread *poll_thread, int tcp_user_timeout_ms);
    raptor_error Start();
    void Shutdown();
    raptor_error Connect(const std::string &addr, intptr_t user);

private:
    void OnEventProcess(EventDetail *detail) override;
    void OnEventProcessImpl(EventDetail *detail);

    void ProcessProperty(SOCKET fd, const Property &p);
    raptor_error InternalConnect(const raptor_resolved_address *addr, intptr_t user,
                                 int timeout_millseconds);
    raptor_error GetConnectExIfNecessary(SOCKET s);

    AsyncConnectObject *FindRecordEntryFromOverlapped(OverLappedEx *p);
    void WorkThread(void *);

private:
    ConnectorHandler *service_;
    bool shutdown_;

    LPFN_CONNECTEX connectex_;

    int tcp_user_timeout_ms_;

    PollingThread *poll_thread_;

    Thread thd_;

    Mutex mtx_;

    ListEntry list_head_;

    AtomicInt64 count_;
    Mutex cmtx_;
    ConditionVariable cv_;
    MultiProducerSingleConsumerQueue mpscq_;
};

} // namespace raptor
#endif // RAPTOR_LITE_SRC_WINDOWS_TCP_CONNECTOR_H_
